package com.yeswater.multithread.chapter4;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * author : yeswater
 * date : 2023/10/23
 *
 * 部分通知线程
 */

public class Run_4_1_7 {
    public static void main(String[] args) throws InterruptedException {
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();

        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();

        Thread.sleep(3000);
        service.signalAllA();
    }

    private static class Service {
        private final Lock lock = new ReentrantLock();
        private final Condition conditionA = lock.newCondition();
        private final Condition conditionB = lock.newCondition();

        public void awaitA() {
            try {
                lock.lock();
                System.out.println("start awaitATime=" + System.currentTimeMillis() + " threadName="
                        + Thread.currentThread().getName());
                conditionA.await();
                System.out.println("end   awaitATime=" + System.currentTimeMillis() + " threadName="
                        + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        public void awaitB() {
            try {
                lock.lock();
                System.out.println("start awaitBTime=" + System.currentTimeMillis() + " threadName="
                        + Thread.currentThread().getName());
                conditionB.await();
                System.out.println("end   awaitBTime=" + System.currentTimeMillis() + " threadName="
                        + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        public void signalAllA() {
            try {
                lock.lock();
                System.out.println("signalAllATime=" + System.currentTimeMillis() + " threadName=" + Thread.currentThread().getName());
                conditionA.signalAll();
            } finally {
                lock.unlock();
            }
        }

        public void signalAllB() {
            try {
                lock.lock();
                System.out.println("signalAllBTime=" + System.currentTimeMillis() + " threadName=" + Thread.currentThread().getName());
                conditionB.signalAll();
            } finally {
                lock.unlock();
            }
        }
    }

    private static class ThreadA extends Thread {
        private final Service service;

        public ThreadA(Service service) {
            this.service = service;
        }

        @Override
        public void run() {
            service.awaitA();
        }
    }

    private static class ThreadB extends Thread {
        private final Service service;

        public ThreadB(Service service) {
            this.service = service;
        }

        @Override
        public void run() {
            service.awaitB();
        }
    }
}
